home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The CICA Windows Explosion!
/
The CICA Windows Explosion! - Disc 2.iso
/
winsock
/
ircii2-6.zip
/
SRC\IRCII-2.6\SOURCE\NEWIO.C
< prev
next >
Wrap
C/C++ Source or Header
|
1995-01-09
|
8KB
|
445 lines
/*
* newio.c: This is some handy stuff to deal with file descriptors in a way
* much like stdio's FILE pointers
*
* IMPORTANT NOTE: If you use the routines here-in, you shouldn't switch to
* using normal reads() on the descriptors cause that will cause bad things
* to happen. If using any of these routines, use them all
*
* Written By Michael Sandrof
*
* Copyright(c) 1990
*
* See the COPYRIGHT file, or do a HELP IRCII COPYRIGHT
*/
#ifndef lint
static char rcsid[] = "@(#)$Id: newio.c,v 1.21 1994/07/03 09:41:00 mrg Stab $";
#endif
#include "irc.h"
#include "ircaux.h"
#ifdef ISC22
# include <sys/bsdtypes.h>
#endif /* ISC22 */
#ifdef ESIX
# include <lan/net_types.h>
#endif /* ESIX */
#include "irc_std.h"
#define IO_BUFFER_SIZE 512
#define WAIT_NL ((unsigned) 0x0001)
#ifdef FDSETSIZE
# define IO_ARRAYLEN FDSETSIZE
#else
# ifdef FD_SETSIZE
# define IO_ARRAYLEN FD_SETSIZE
# else
# define IO_ARRAYLEN NFDBITS
# endif
#endif
typedef struct myio_struct
{
char buffer[IO_BUFFER_SIZE + 1];
unsigned int read_pos,
write_pos;
unsigned misc_flags;
#if defined(ESIX) || defined(_Windows)
unsigned flags;
#endif /* ESIX */
#ifdef _Windows
int fd;
#endif
} MyIO;
#define IO_SOCKET 1
static struct timeval right_away = { 0L, 0L };
static MyIO *io_rec[IO_ARRAYLEN];
#ifdef _Windows
#define get_ior(x) (*get_io_rec(x))
MyIO **get_io_rec(int fd)
{
int i;
for (i = 0; i < IO_ARRAYLEN; i++)
{
if (io_rec[i] && io_rec[i]->fd == fd)
return &io_rec[i];
}
for (i = 0; i < IO_ARRAYLEN; i++)
{
if (!io_rec[i])
return &io_rec[i];
}
}
#else
#define get_ior(x) io_rec[x]
#endif
static struct timeval dgets_timer;
static struct timeval *timer;
int dgets_errno = 0;
MyIO * new_io_rec(int fd)
{
MyIO *rec;
rec = (MyIO *) new_malloc(sizeof(MyIO));
rec->read_pos = 0;
rec->write_pos = 0;
rec->flags = 0;
#ifdef _Windows
rec->fd = fd;
#endif
return rec;
}
#if defined(ESIX) || defined(_Windows)
static void init_io();
/* Esix must know if it is a socket or not. */
void mark_socket(int des)
{
MyIO **rec;
init_io();
rec = & get_ior(des);
if (*rec == (MyIO *) 0)
*rec = new_io_rec(des);
(*rec)->flags |= IO_SOCKET;
}
void unmark_socket(int des)
{
MyIO **rec;
init_io();
rec = & get_ior(des);
if (*rec == (MyIO *) 0)
*rec = new_io_rec(des);
(*rec)->flags &= ~IO_SOCKET;
}
#endif /* ESIX || _Windows */
/*
* dgets_timeout: does what you'd expect. Sets a timeout in seconds for
* dgets to read a line. if second is -1, then make it a poll.
*/
extern time_t
dgets_timeout(sec)
int sec;
{
time_t old_timeout = dgets_timer.tv_sec;
if (sec)
{
dgets_timer.tv_sec = (sec == -1) ? 0 : sec;
dgets_timer.tv_usec = 0;
timer = &dgets_timer;
}
else
timer = (struct timeval *) 0;
return old_timeout;
}
static void init_io()
{
static int first = 1;
if (first)
{
int c;
for (c = 0; c < IO_ARRAYLEN; c++)
io_rec[c] = (MyIO *) 0;
(void) dgets_timeout(-1);
first = 0;
}
}
/*
* dgets: works much like fgets except on descriptor rather than file
* pointers. Returns the number of character read in. Returns 0 on EOF and
* -1 on a timeout (see dgets_timeout())
*/
int dgets(str, len, des, specials)
char *str;
int len;
int des;
char *specials;
{
char *ptr, ch;
int cnt = 0,
c;
fd_set rd;
int WantNewLine = 0;
int BufferEmpty;
int i,
j;
MyIO **rec;
init_io();
rec = & get_ior(des);
if (*rec == (MyIO *) 0)
*rec = new_io_rec(des);
if (len < 0)
{
WantNewLine = 1;
len = (-len);
(*rec)->misc_flags |= WAIT_NL;
}
while (1)
{
if ((BufferEmpty = ((*rec)->read_pos ==
(*rec)->write_pos)) || WantNewLine)
{
if(BufferEmpty)
{
(*rec)->read_pos = 0;
(*rec)->write_pos = 0;
}
FD_ZERO(&rd);
FD_SET(des, &rd);
switch (select(des + 1, &rd, 0, 0, timer))
{
case 0:
str[cnt] = (char) 0;
dgets_errno = 0;
return (-1);
default:
#if defined(ESIX) || defined(_Windows)
if ((*rec)->flags & IO_SOCKET)
{
#ifdef _Windows
WSASetLastError(0);
#endif
c = recv(des, (*rec)->buffer +
(*rec)->write_pos,
IO_BUFFER_SIZE-(*rec)->write_pos,
0);
}
else
#endif /* ESIX */
c = read(des, (*rec)->buffer +
(*rec)->write_pos,
IO_BUFFER_SIZE-(*rec)->write_pos);
if (c <= 0)
{
#ifdef _Windows
if ((*rec)->flags & IO_SOCKET)
{
dgets_errno == WSAGetLastError();
if (dgets_errno == WSAEWOULDBLOCK ||
dgets_errno == WSAEINTR)
{
return -1;
}
return 0;
}
else
{
dgets_errno = errno;
return 0;
}
#else
dgets_errno = errno;
return 0;
#endif
}
if (WantNewLine && specials)
{
ptr = (*rec)->buffer;
for (i = (*rec)->write_pos;
i < (*rec)->write_pos+c;i++)
/* This section re-indented - phone, jan 1993 */
{
if((ch = ptr[i]) == specials[0])
{
if (i > 0)
{
bcopy(ptr + i - 1, ptr + i + 1,
(*rec)->write_pos +
c - i - 1);
i -= 2;
c -= 2;
}
else
{
bcopy(ptr, ptr + 1,
(*rec)->write_pos +
c - 1);
i--;
c--;
}
}
else if (ch == specials[2])
{
for (j = i - 1; j >= 0 &&
isspace(ptr[j]); j--)
;
for (;j >= 0 && !isspace(ptr[j]); j--)
;
bcopy(ptr + j + 1, ptr + i + 1,
(*rec)->write_pos + c - i - 1);
c -= (i - j);
i = j;
}
else if (ch == specials[1])
{
for (j = i - 1;
j >= 0 && ptr[j] != '\n'; j--);
bcopy(ptr + j + 1, ptr + i + 1,
(*rec)->write_pos + c - i - 1);
c -= (i-j);
i = j;
}
}
}
(*rec)->write_pos += c;
break;
}
}
ptr = (*rec)->buffer;
if (WantNewLine)
{
for (cnt = (*rec)->write_pos; cnt > 0;cnt--,ptr++)
{
if (*ptr == '\n' || cnt == len-1)
{
*ptr = '\0';
(void) strcpy(str, (*rec)->buffer);
(*rec)->write_pos=cnt-1;
bcopy((*rec)->buffer, ptr, cnt);
dgets_errno = 0;
return 1;
}
}
return -2;
}
while ((*rec)->read_pos < (*rec)->write_pos)
{
if (((str[cnt++] = ptr[((*rec)->read_pos)++])
== '\n') || (cnt == len))
{
dgets_errno = 0;
str[cnt] = (char) 0;
return (cnt);
}
}
}
}
/*
* new_select: works just like select(), execpt I trimmed out the excess
* parameters I didn't need.
*/
int new_select(rd, wd, timeout)
fd_set *rd,
*wd;
struct timeval *timeout;
{
int i,
set = 0;
fd_set new;
struct timeval *newtimeout,
thetimeout;
if (timeout)
{
newtimeout = &thetimeout;
bcopy(timeout, newtimeout, sizeof(struct timeval));
}
else
newtimeout = NULL;
init_io();
FD_ZERO(&new);
for (i = 0; i < IO_ARRAYLEN; i++)
{
if (io_rec[i] && !(io_rec[i]->misc_flags&WAIT_NL))
{
if (io_rec[i]->read_pos < io_rec[i]->write_pos)
{
#ifdef _Windows
FD_SET(io_rec[i]->fd, &new);
#else
FD_SET(i, &new);
#endif
set = 1;
}
}
}
if (set)
{
set = 0;
if (!(select(IO_ARRAYLEN, rd, wd, NULL, &right_away) > 0))
FD_ZERO(rd);
for (i = 0; i < IO_ARRAYLEN; i++)
{
if ((FD_ISSET(i, rd)) || (FD_ISSET(i, &new)))
{
set++;
FD_SET(i, rd);
}
else
FD_CLR(i, rd);
}
return (set);
}
return (select(IO_ARRAYLEN, rd, wd, NULL, newtimeout));
}
/* new_close: works just like close */
void new_close(des)
int des;
{
#ifdef ESIX
if (get_ior(des)->flags & IO_SOCKET)
t_close(des);
#endif /* ESIX */
#ifdef _Windows
if (get_ior(des)->flags & IO_SOCKET)
closesocket(des);
#else
close(des)
#endif
new_free(&(get_ior(des)));
#ifndef _Windows
close(des);
#endif
}
/* set's socket options */
extern void
set_socket_options(s)
int s;
{
#if defined(ESIX) || defined(_Windows)
mark_socket(s);
#else
#ifndef NO_STRUCT_LINGER
struct linger lin;
#endif
int opt = 1;
int optlen = sizeof(opt);
(void) setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &opt, optlen);
opt = 1;
(void) setsockopt(s, SOL_SOCKET, SO_KEEPALIVE, &opt, optlen);
#ifndef NO_STRUCT_LINGER
lin.l_onoff = lin.l_linger = 0;
(void) setsockopt(s, SOL_SOCKET, SO_LINGER, &lin, optlen);
#endif /* NO_STRUCT_LINGER */
#endif /* ESIX */
}